using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using UnityEditor;
using UnityEngine;

public class NetClient : MonoBehaviour
{
    private TcpClient tcpClient;
    private NetworkStream tcpStream;
    private const int bufferSize = 1024 * 64;
    private byte[] buffer = new byte[bufferSize];
    private MemoryStream memoryStream;
    private BinaryReader binaryReader;

    public NetClient()
    {
        memoryStream = new MemoryStream();
        binaryReader = new BinaryReader(memoryStream);
    }

    //连接服务器，传入IP地址（host）和端口号（port）
    public void OnConnectSever(string host, int port)
    {
        try
        {
            //根据传入的host获取IP地址
            IPAddress[] addresses = Dns.GetHostAddresses(host);

            if(addresses.Length == 0)
            {
                Debug.Log("host invalid");
                return;
            }

            if (addresses[0].AddressFamily == AddressFamily.InterNetworkV6) 
                tcpClient = new TcpClient(AddressFamily.InterNetworkV6);
            else
                tcpClient = new TcpClient(AddressFamily.InterNetwork);

            tcpClient.SendTimeout = 1000;
            tcpClient.ReceiveTimeout = 1000;
            tcpClient.NoDelay = true;
            tcpClient.BeginConnect(host, port, OnConnect, null);
        }
        catch (System.Exception e)
        {

            Debug.LogError(e.Message);
        }
    }

    private void OnConnect(IAsyncResult asyncResult)
    {
        if(tcpClient == null || !tcpClient.Connected)
        {
            Debug.LogError("connect sever error");
            return;
        }
        Manager.Net.OnNetConnected();
        tcpStream = tcpClient.GetStream();
        tcpStream.BeginRead(buffer, 0, bufferSize, OnRead, null);
    }

    private void OnRead(IAsyncResult asyncResult)
    {
        try
        {
            if (tcpClient == null || tcpStream == null)
                return;

            if(buffer.Length < 1) 
            {
                OnDisConnected();
                return;
            }

            ReceiveData();
            
            //接受数据完成后清空数据流并读取新数据
            lock (tcpStream) 
            {
                Array.Clear(buffer, 0, buffer.Length);
                tcpStream.BeginRead(buffer, 0, bufferSize, OnRead, null);
            }
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
            OnDisConnected();
        }
    }

    public void OnDisConnected()
    {
        if(tcpClient != null && tcpClient.Connected) 
        {
            tcpClient.Close();
            tcpClient = null;

            tcpStream.Close();
            tcpStream = null;
        }

        Manager.Net.OnDisconnected();
    }

    /// <summary>
    /// 解析数据
    /// </summary>
    private void ReceiveData()
    {
        //从末尾开始写入
        memoryStream.Seek(0, SeekOrigin.End);
        memoryStream.Write(buffer, 0, buffer.Length);

        //写入完成后从头开始读取
        memoryStream.Seek(0, SeekOrigin.Begin);

        while(RemainingBytesLength() >= 8)
        {
            int msgId = binaryReader.ReadInt32();
            int msgLen = binaryReader.ReadInt32();

            if(RemainingBytesLength() >= msgLen)
            {
                byte[] data = binaryReader.ReadBytes(msgLen);
                string message = System.Text.Encoding.UTF8.GetString(data);

                Manager.Net.Receive(msgId, message);
            }
            else
            {
                memoryStream.Position = memoryStream.Position - 8;
                break;
            }
        }

        byte[] leftover = binaryReader.ReadBytes(RemainingBytesLength());
        memoryStream.SetLength(0);
        memoryStream.Write(leftover, 0, leftover.Length);
    }

    private int RemainingBytesLength()
    {
        return (int)(memoryStream.Length - memoryStream.Position);
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    /// <param name="msgId"></param>
    /// <param name="message"></param>
    public void SendMessaage(int msgId, string message)
    {
        using (MemoryStream ms = new MemoryStream()) 
        {
            ms.Position = 0;
            BinaryWriter binaryWriter = new BinaryWriter(ms);

            byte[] data = System.Text.Encoding.UTF8.GetBytes(message);

            binaryWriter.Write(msgId);
            binaryWriter.Write((int)data.Length);
            binaryWriter.Write(data);
            binaryWriter.Flush();

            if(tcpClient != null && tcpClient.Connected) 
            {
                byte[] sendData = ms.ToArray();
                tcpStream.BeginWrite(sendData, 0, sendData.Length, OnEndSend, null);
            }
            else
            {
                Debug.LogError("服务器未连接"); 
            }
        }
    }

    private void OnEndSend(IAsyncResult ar)
    {
        try
        {
            tcpStream.EndWrite(ar);
        }
        catch (Exception e)
        {
            OnDisConnected();
            Debug.LogError(e.Message);
        }
    }
}
